//=============================================================================
// SentinelShield - Protects sentinel from 100% of damage.
//=============================================================================
class SentinelShield extends SentinelUpgrade;

var() int ShieldAmount;
var() sound AbsorbSound, DrainedSound;

var ShieldSphere ShieldSphere;
var float LastHitTime;

struct HitDataStruct
{
	var vector HitLocation;
	var vector HitNormal;
};

var HitDataStruct HitData;
var byte HitCount, LastHitCount;

replication
{
    reliable if (Role == Role_Authority)
        ShieldAmount,ShieldSphere;
	unreliable if(Role == ROLE_Authority)
		HitCount, HitData;
}

function InitFor(Sentinel S)
{
	Super.InitFor(S);

	ShieldSphere = spawn(class'ShieldSphere', S);

	if(ShieldSphere == None)
		warn("Failed to spawn collision sphere for"@self);

	ShieldSphere.Shield = self;
	ShieldSphere.SetLocation(S.Location + S.CentreOffset);
	ShieldSphere.SetBase(S);
}

//Sentinel can't be damaged whilst shield is up (some damage does get through shield and so must be stopped here).
function NotifyTakeDamage(out int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType)
{
	ShieldAmount -= Damage;

	if(ShieldAmount > 0)
	{
		Damage = 0;

		if(Level.TimeSeconds - LastHitTime > 0.1)
		{
			HitCount++;
			HitData.HitLocation = ShieldSphere.Location + normal(HitLocation - Location) * 64 * ShieldSphere.DrawScale;
			HitData.HitNormal = HitLocation - ShieldSphere.Location;

			if(Level.NetMode != NM_DedicatedServer)
				HitEffects();

			LastHitTime = Level.TimeSeconds;
		}

		Super.NotifyTakeDamage(Damage, EventInstigator, HitLocation, Momentum, DamageType);
	}
	else
	{
		Damage = Abs(ShieldAmount);
		PlaySound(DrainedSound);

		Super.NotifyTakeDamage(Damage, EventInstigator, HitLocation, Momentum, DamageType);

		RemoveUpgrade();
		tfgri(level.game.gamereplicationinfo).control[sentinel.myteam]-=200;
	}
}

simulated function HitEffects()
{
	PlaySound(AbsorbSound);
	spawn(class'ShieldHitEffect',,, HitData.HitLocation, rotator(HitData.HitNormal));
}

simulated event PostNetReceive()
{
	if(HitCount != LastHitCount)
	{
		HitEffects();
		LastHitCount = HitCount;
	}
}

function ShieldAbsorb(int Damage, Pawn EventInstigator, vector HitLocation, vector Momentum, class<DamageType> DamageType)
{
	Sentinel.TakeDamage(Damage, EventInstigator, HitLocation, Momentum, DamageType);
}

function Destroyed()
{
	if(ShieldSphere != None)
		ShieldSphere.Destroy();
}

defaultproperties
{
     ShieldAmount=1000
     AbsorbSound=Sound'TFMedia.ShieldAbsorb'
     DrainedSound=Sound'TFMedia.ShieldDrained'
     AmmoCost=1
     UpgradeName="Molecular Shield"
     Description="A molecular shield to provide complete protection from any and all weapons a Sentinel is likely to be faced with whilst allowing the Sentinel to continue firing unaffected. The standard battery fitted provides enough power to absorb substantial punishment before running out.||The shield will detect the presence of a deployer held by an ally and will deactivate locally, allowing repairs and upgrades to be carried out without disrupting the integrity of the shield as a whole."
     ActivateSound=Sound'TFMedia.ShieldActivate'
     bNetNotify=True
}
